#region File Header
//-----------------------------------------------------------------------------
// SibLib
//
// Copyright (C) 2010 Julien Villers
// This program is distributed under the terms of the 
// GNU Lesser General Public License (LGPL).
// See Docs/lgpl.txt and Docs/gpl.txt
//
// This file is based on the XML Particles Sample (C) Microsoft.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using Microsoft.Xna.Framework;
#endregion

namespace SibLib
{
    /// <summary>
    /// Static methods to assist with random-number generation.
    /// </summary>
    static public class RandomMath
    {
        #region Random Singleton


        /// <summary>
        /// The Random object used for all of the random calls.
        /// </summary>
        private static Random random = new Random();
        public static Random Random
        {
            get { return random; }
        }


        #endregion

        #region Single Variations

        /// <summary>
        /// Generate a random floating-point value between the minimum and 
        /// maximum values provided.
        /// </summary>
        /// <remarks>This is similar to the Random.Next method, substituting singles
        /// for integers.</remarks>
        /// <param name="minimum">The minimum value.</param>
        /// <param name="maximum">The maximum value.</param>
        /// <returns>A random floating-point value between the minimum and maximum v
        /// alues provided.</returns>
        public static float RandomBetween(float minimum, float maximum)
        {
            return minimum + (float)random.NextDouble() * (maximum - minimum);
        }

        #endregion

        #region Direction Generation

        /// <summary>
        /// Generate a random direction vector.
        /// </summary>
        /// <returns>A random direction vector in 2D space.</returns>
        public static Vector2 RandomDirection()
        {
            float angle = RandomBetween(0, MathHelper.TwoPi);
            return new Vector2((float)Math.Cos(angle),
                (float)Math.Sin(angle));
        }

        /// <summary>
        /// Generate a random direction vector within constraints.
        /// </summary>
        /// <param name="minimumAngle">The minimum angle.</param>
        /// <param name="maximumAngle">The maximum angle.</param>
        /// <returns>
        /// A random direction vector in 2D space, within the constraints.
        /// </returns>
        public static Vector2 RandomDirection(float minimumAngle, float maximumAngle)
        {
            float angle = RandomBetween(MathHelper.ToRadians(minimumAngle),
                MathHelper.ToRadians(maximumAngle)) - MathHelper.PiOver2;
            return new Vector2((float)Math.Cos(angle),
                (float)Math.Sin(angle));
        }

        #endregion

        #region Vector generation

        /// <summary>
        /// Generate a random vector with same range for X and Y.
        /// </summary>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static Vector2 RandomVector2(float minValue, float maxValue)
        {
            return new Vector2(RandomBetween(minValue, maxValue), RandomBetween(minValue, maxValue));
        }

        /// <summary>
        /// Generate a random vector with different ranges for X and Y.
        /// </summary>
        /// <param name="minVector"></param>
        /// <param name="maxVector"></param>
        /// <returns></returns>
        public static Vector2 RandomVector2Between(Vector2 minVector, Vector2 maxVector)
        {
            return new Vector2(RandomBetween(minVector.X, maxVector.X), RandomBetween(minVector.Y, maxVector.Y));
        }

        public static Vector3 RandomVector3(float minValue, float maxValue)
        {
            return new Vector3(RandomBetween(minValue, maxValue), RandomBetween(minValue, maxValue), RandomBetween(minValue, maxValue));
        }
        #endregion

        #region Angle Generation

        /// <summary>
        /// Return a random angle between 0 and 2xPi.
        /// </summary>
        /// <returns>Angle value.</returns>
        public static float RandomAngle()
        {
            return RandomAngle(0.0f, MathHelper.TwoPi);
        }

        /// <summary>
        /// Return a random angle between 0 and maximum.
        /// </summary>
        /// <remarks>
        /// Value is ensured to be between 0 and 2xPi, even is maximum is above.
        /// </remarks>
        /// <returns>Angle value.</returns>
        public static float RandomAngle(float maximum)
        {
            return MathHelper.WrapAngle(RandomAngle(0.0f, maximum));
        }

        /// <summary>
        /// Return a random angle between minimum and maximum.
        /// </summary>
        /// <remarks>
        /// Value is ensured to be between 0 and 2xPi, even is minimum/maximum aren't between 0 and 2xPi.
        /// </remarks>
        /// <returns>Angle value.</returns>
        public static float RandomAngle(float minimum, float maximum)
        {
            return MathHelper.WrapAngle(RandomBetween(minimum, maximum));
        }

        #endregion
    }
}
